#pragma once
#include "mutex.hpp"
#include "sem.hpp"
#include <vector>

template<class T>
class RingQueue
{
    public:

    RingQueue(int capacity = 5):_capacity(capacity),_front(0),_rear(0),_p_sem(capacity),_c_sem(0)
    {}

    ~RingQueue()
    {}

    void Push(const T& data)
    {
        //生产者申请空间，释放数据
        _p_sem.P();
        LockGuard lg(_p_mutex);
        _rq.push_back(data);
        _rear = (_rear + 1) % _capacity;
        lg.~LockGuard();
        _c_sem.V();
    }

    void Pop(T* out)
    {
        //消费者申请数据，释放空间
        _c_sem.P();
        LockGuard lg(_c_mutex);
        *out = _rq[_front++];
        _front %= _capacity;
        lg.~LockGuard();
        _p_sem.V();
    }

    private:
    std::vector<T> _rq;//环形队列基于顺序表实现
    int _capacity;//最大容量，需空一个标志位
    int _front;//前指针，用于消费者
    int _rear;//后指针，用于生产者

    Mutex _p_mutex;//生产者互斥锁
    Mutex _c_mutex;//消费者互斥锁

    Sem _p_sem;//生产者信号量
    Sem _c_sem;//消费者信号量
};